using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Linq;
using System.ComponentModel;
using System.Xml.Serialization;
using System.Xml;
using System.Runtime.Serialization;


namespace Nizm0.QOT.Library.Objects
{
    [Serializable]
    [XmlRoot("ProcedureInfo")]
    public class ProcedureInfo : Library.Objects.IProcedureInfo, Library.Objects.IProcedureStatus, IXmlSerializable, ISerializable
    {
        private string _procedureName;
        private bool _isopen = false;
        private bool _looking = true;
        private bool _startFromTheLatestData;
        private bool _isstarted = false;
        private ProcedureInfo.Status _status;
        private DateTime _starttime;
        private DateTime _endtime;
        private DateTime _dateOfLastDataFound;
        private int _found = 0;
        private bool _saved;
        private bool _visible;
        [NonSerialized]
        private List<Procedure> _procedureList = new List<Procedure>();
        [NonSerialized]
        private List<ProcedureVersion> _knownVersionList = new List<ProcedureVersion>();
        [NonSerialized]
        private string _resultFile;
        private LocalFile test;// = new LocalFile();
        [NonSerialized]
        private Result _result;
        [NonSerialized]
        private List<Library.Objects.Query> _queryList = new List<Query>();
        private List<SearchedObject> _searchedObjectsList = new List<SearchedObject>();
            
        public enum Status { Started = 1, Waiting, Ended, Force, Writing, Prepering, Nothing, Canceled, Opened, Ready, Changed, Error, Loaded, Added };

        #region Dalegates
        public delegate void ChangeStatusEvetHendler(String str);
        public static event ChangeStatusEvetHendler NewStatus;

        public delegate void ErrorEventHandler(object sender, Exception ex);
        public static event ErrorEventHandler ErrorEvent;

        public delegate void ProcedureResultInformationLookingValueChangedHandler(object sender, bool e);
        public event ProcedureResultInformationLookingValueChangedHandler LookingValueChanged;

        public delegate void EventNewVersionAdd(Object sender, IProcedure proc);
        public static event EventNewVersionAdd NewVersionAdd;
        public delegate void EventVersionChange(object sender, VersionChangeEventArgs e);
        public static event EventVersionChange VersionChange;
        public static event EventNewVersionAdd ProcedureUpdate;

        public event Result.DelegateInStartMethod ProcedureStart;
        public event Result.DelegateLookingProcedureEnds ProcedureEnds;

        public delegate void NewQuedyAddHandler(object sender, NewQueryFoundEventArgs e);
        public event NewQuedyAddHandler NewQuedyAdd;

        public delegate void EventOnStatusChange(Object sender, ProcedureInfo.Status e);
        public event EventOnStatusChange StatusChange;

        public event EventHandler FinishedSearchObject;

        public static void SetStatusChangeEvent(ChangeStatusEvetHendler method)
        {
            bool notfound = true;

            if (NewStatus != null)
            {
                foreach (var tmpmethod in NewStatus.GetInvocationList())
                {
                    if (method == tmpmethod)
                        notfound = false;
                }
            }
            if (notfound)
                NewStatus += method;
        }

        public static void SetErrorEvent(ErrorEventHandler method)
        {
            bool notfound = true;

            if (ErrorEvent != null)
            {
                foreach (var tmpmethod in ErrorEvent.GetInvocationList())
                {
                    if (method == tmpmethod)
                        notfound = false;
                }
            }
            if (notfound)
                ErrorEvent += method;
        }

        public static void SetNewVersionAddEvent(EventNewVersionAdd method)
        {
            bool notfound = true;

            if (NewVersionAdd != null)
            {
                foreach (var tmpmethod in NewVersionAdd.GetInvocationList())
                {
                    if (method == tmpmethod)
                        notfound = false;
                }
            }
            if (notfound)
                NewVersionAdd += method;
        }

        public static void SetVersionChangeEvent(EventVersionChange method)
        {
            bool notfound = true;

            if (VersionChange != null)
            {
                foreach (var tmpmethod in VersionChange.GetInvocationList())
                {
                    //ReferenceEquals(method, tmpmethod);
                    if (method == tmpmethod)
                        notfound = false;
                }
            }
            if (notfound)
                VersionChange += method;
        }

        public static void SetProcedureUpdateEvent(EventNewVersionAdd method)
        {
            bool notfound = true;

            if (ProcedureUpdate != null)
            {
                foreach (var tmpmethod in ProcedureUpdate.GetInvocationList())
                {
                    if (method == tmpmethod)
                        notfound = false;
                }
            }
            if (notfound)
                ProcedureUpdate += method;
        }

        public static void SetEventOnLookingChange(ProcedureResultInformationLookingValueChangedHandler method)
        {
            //bool notfound = true;

            //if (LookingValueChanged != null)
            //{
            //    foreach (var tmpmethod in LookingValueChanged.GetInvocationList())
            //    {
            //        if (method == tmpmethod)
            //            notfound = false;
            //    }
            //}
            //if (notfound)
            //    LookingValueChanged += method;
        }

        private void Result_BeforeStartMethod(object sender, EventArgs e)
        {
            OnProcedureStarts(sender, e);
            //ProcedureEnds(this);
        }

        private void Result_LookingProcedureUpdate(ProcedureInfo procedure, ProcedureInfo.Status status)
        {
            procedure.QuerySearchingStatus = status;

        }

        private void Result_LookingProcedureEnds(ProcedureInfo procedure)
        {
            procedure.Looking = false;
            OnProcedureEnds(this, new EventArgs());
            Save();
        }

        private void Result_NewQueryFound(object sender, ReturnFullRowEventHandler e)
        {
            OnNewQueryFounded(sender, e);
        }

        private void Result_FinishedSearchObject(object sender, FinishedSearchObjectEventArgs e)
        {
            if (!_searchedObjectsList.Exists(t => object.ReferenceEquals(t.Table, e.LocalObject)))
                _searchedObjectsList.Add(new SearchedObject(e.LocalObject, e.Path, e.Finished));
            else
                _searchedObjectsList.Find(t => object.ReferenceEquals(t.Table, e.LocalObject)).FinishedAt = e.Finished;
        }
        #endregion

        #region Propertiess
        /// <summary>
        /// Name of procedure
        /// </summary>
        [XmlAttribute("Name")]
        [CategoryAttribute("Misc")]
        public string Name
        {
            get
            {
                return _procedureName;
            }
            set
            {
                _procedureName = value;
            }
        }
        /// <summary>
        /// If window with results is oupen
        /// </summary>
        [XmlIgnore()]
        [CategoryAttribute("Additional Info")]
        public bool IsOpen
        {
            get { return _isopen; }
            set { _isopen = value; }
        }
        /// <summary>
        /// If program is looking for queries
        /// </summary>
        [XmlIgnore()]
        [CategoryAttribute("Config")]
        public bool Looking
        {
            get { return _looking; }
            set
            {
                if (LookingValueChanged != null && _looking != value)
                {
                    _looking = value;
                    LookingValueChanged(this, value);
                }
            }
        }
        /// <summary>
        /// If the search starts from the latest data
        /// </summary>  
        [XmlIgnore()]
        [CategoryAttribute("Config")]
        public bool StartFromTheLatestData
        {
            get { return _startFromTheLatestData; }
            set { _startFromTheLatestData = value; }
        }
        /// <summary>
        /// If the search is started
        /// </summary>  
        [XmlIgnore()]
        [CategoryAttribute("Additional Info"), ReadOnlyAttribute(true)]
        public bool IsStarted
        {
            get { return _isstarted; }
            set
            {
                _isstarted = value;
                //OnPropertyChanged(() => HotkeysForeground);
            }
        }
        /// <summary>
        /// Actual status of thys procedure
        /// </summary>
        [XmlIgnore()]
        [CategoryAttribute("Misc"), ReadOnlyAttribute(true)]
        public ProcedureInfo.Status QuerySearchingStatus
        {
            get { return _status; }
            set
            {
                _status = value;
                OnStatusChange(this, value);
            }
        }
        /// <summary>
        /// When program starts looking for queries
        /// </summary>
        [XmlIgnore()]
        [CategoryAttribute("Additional Info"), ReadOnlyAttribute(true)]
        public DateTime StartTime
        {
            get { return _starttime; }
            set { _starttime = value; }
        }
        /// <summary>
        /// When program ends looking for queries
        /// </summary>
        [XmlIgnore()]
        [CategoryAttribute("Additional Info"), ReadOnlyAttribute(true)]
        public DateTime EndTime
        {
            get { return _endtime; }
            set { _endtime = value; }
        }
        /// <summary>
        /// How many queries whos found
        /// </summary>
        [XmlIgnore()]
        [CategoryAttribute("Additional Info"), ReadOnlyAttribute(true)]
        public int Found
        {
            get { return _found; }
            set { _found = value; }
        }
        /// <summary>
        /// Date of last data found
        /// </summary>
        [XmlAttribute("DateOfLastDataFound")]
        [CategoryAttribute("Additional Info"), ReadOnlyAttribute(true)]
        public DateTime DateOfLastDataFound
        {
            get { return _dateOfLastDataFound; }
            set { _dateOfLastDataFound = value; }
        }
        /// <summary>
        /// If found results are saved
        /// </summary>
        [XmlIgnore()]
        [CategoryAttribute("Additional Info"), ReadOnlyAttribute(true)]
        public bool Saved
        {
            get { return _saved; }
            set { _saved = value; }
        }
        /// <summary>
        /// If window with queries is visible
        /// </summary>
        [XmlIgnore()]
        [CategoryAttribute("Additional Info"), ReadOnlyAttribute(true)]
        public bool Visible
        {
            get { return _visible; }
            set { _visible = value; }
        }
        //[XmlIgnore()]
        [CategoryAttribute("Additional Info")]
        public List<Procedure> ProcedureList
        {
            get { return _procedureList; }
            set { _procedureList = value; }
        }
        [XmlIgnore()]
        [CategoryAttribute("Additional Info")]
        public List<ProcedureVersion> KnownVersionList
        {
            get { return _knownVersionList; }
            set { _knownVersionList = value; }
        }
        [XmlAttribute("ResultFile")]
        [CategoryAttribute("Misc")]
        public string ResultFile
        {
            get
            {
                if (string.IsNullOrWhiteSpace(_resultFile))
                {
                    _resultFile = string.Format("{0}{1}.{2}",
                        Settings.Instance.ProjectSettings.ProjectLocation.EndsWith("\\") ? Settings.Instance.ProjectSettings.ProjectLocation : Settings.Instance.ProjectSettings.ProjectLocation + '\\',
                        this.Name,
                        "txt");
                }
                return _resultFile;
            }
            set
            {
                _resultFile = value;
                if (!string.IsNullOrWhiteSpace(value) && _queryList.Count == 0)
                    Load();
            }
        }
        [XmlElement("ResultList")]
        [CategoryAttribute("Misc")]
        public List<Library.Objects.Query> ResultList
        {
            get
            {
                if (!string.IsNullOrWhiteSpace(_resultFile) && _queryList.Count == 0)
                    Load();
                return _queryList;
            }
            set
            {
                _queryList = value;
            }
        }
        [XmlIgnore()]
        [CategoryAttribute("Misc")]
        public List<SearchedObject> SearchedObjectsList
        {
            get { return _searchedObjectsList; }
            set { _searchedObjectsList = value; }
        }
        #endregion

        #region Constructors
        /// <summary>
        /// Constructor with procedure name
        /// </summary>
        /// <param name="procedure"></param>
        public ProcedureInfo(string procedure)
            : this()
        {
            _procedureName = procedure;
        }
        public ProcedureInfo(ProcedureInfo procedure)
            : this()
        {
            _procedureName = procedure._procedureName;
            _isopen = procedure._isopen;
            _looking = procedure._looking;
            QuerySearchingStatus = procedure._status;
            _starttime = procedure._starttime;
            _endtime = procedure._endtime;
            _found = procedure._found;
            _saved = procedure._saved;
            _visible = procedure._visible;
        }
        public ProcedureInfo(string name, bool isopen, bool looking, int found, DateTime starttime, DateTime endtime)
            : this()
        {
            _procedureName = name;
            _isopen = isopen;
            _looking = looking;
            //_status = status;
            _starttime = starttime;
            _endtime = endtime;
            _found = found;
            //_saved = saved;
            //_visible = visible;
        }
        public ProcedureInfo()
        {
            _result = new Result(this);
            _result.LookingProcedureUpdate += new Result.DelegateLookingProcedureUpdate(Result_LookingProcedureUpdate);
            _result.LookingProcedureEnds += new Result.DelegateLookingProcedureEnds(Result_LookingProcedureEnds);
            //ProcedureEnds;
            _result.BeforeStartMethod += new Result.DelegateInStartMethod(Result_BeforeStartMethod);
            //ProcedureStart;
            _result.NewQueryFound += new Result.DelegateNewQueryFound(Result_NewQueryFound);
            _result.FinishedSearchObject += new FinishedSearchObjectEventHandler(Result_FinishedSearchObject);
            //_result.LookingProcedureEnds += new Result.DelegateLookingProcedureEnds(_result_LookingProcedureEnds);
            //_result.LookingProcedureEnds += new Library.Forms.frmResult.DelegateLookingProcedureEnds(EndProces);t()
        
            //Load();
        }


        ~ProcedureInfo()
        {
            try
            {
                _result.LookingProcedureEnds -= Result_LookingProcedureEnds;
                _result.BeforeStartMethod -= Result_BeforeStartMethod;
                _result.NewQueryFound -= Result_NewQueryFound;
                //_result.LookingProcedureEnds -= _result_LookingProcedureEnds;
            }
            catch
            { }
        }
        #endregion

        #region Methods

        public void Start()
        {
            OnProcedureStarts(this, new EventArgs());
            if (!_startFromTheLatestData)
                _queryList.Clear();
            _result.Start();


            //_started = true;
            //_finished = false;

            ////TimerCallback tcb = timer_Tick;
            //_myThrTimer = new System.Threading.Timer((TimerCallback)timer_Tick, new AutoResetEvent(false), 0, 1);
            //_serchStopWatch.Reset();
            //_serchStopWatch.Start();
            //NotSaved();
            //OnLookingProcedureUpdate(_parent, Status);

            //_parent.StartTime = System.DateTime.Now;

            //ThreadPool.QueueUserWorkItem(new WaitCallback(FindQueries));

        }

        public void End()
        {
            OnProcedureEnds(this, new EventArgs());
            _result.Abort();
        }

        private void Save()
        {
            try
            {
                using (XmlTextWriter xml = new XmlTextWriter(ResultFile + "tmp", Encoding.UTF8) { Formatting = Formatting.Indented })
                {
                    var nsSerializer = new XmlSerializerNamespaces();
                    nsSerializer.Add("", "");

                    var xmlSerializer = new System.Xml.Serialization.XmlSerializer(_queryList.GetType(), "");
                    xmlSerializer.Serialize(xml, _queryList, nsSerializer);
                    xml.Close();
                }
                //using (Stream str = new MemoryStream())
                //{
                //    //System.Runtime.Serialization.Formatters.Binary.BinaryFormatter t = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(
                //    System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(List<Query>));
                //    x.Serialize(str, _queryList);
                //    XmlDocument xDocument = new XmlDocument();
                //    str.Position = 0;
                //    xDocument.Load(str);
                //    using (StreamWriter strw = new StreamWriter(_resultFile + "tmp"))
                //    {
                //        strw.Write(xDocument.OuterXml);
                //        strw.Close();
                //    }
                //}
            }
            catch (Exception ex)
            {
            }
        }

        private void Load()
        {
            if (!string.IsNullOrWhiteSpace(ResultFile) && File.Exists(ResultFile + "tmp"))
            {
                using (StreamReader strr = new StreamReader(ResultFile + "tmp"))
                {
                    byte[] byteArray = Encoding.ASCII.GetBytes(strr.ReadToEnd());
                    MemoryStream stream = new MemoryStream(byteArray);
                    System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(_queryList.GetType());
                    _queryList = (List<Query>)x.Deserialize(stream);
                    //_result.Load(_queryList);
                    //return ip;
                    strr.Close();
                }
            }
        }

        private void OnProcedureStarts(object sender, EventArgs e)
        {
            if (ProcedureStart != null)
                ProcedureStart(sender, e);
        }

        private void OnProcedureEnds(object sender, EventArgs e)
        {
            if (ProcedureEnds != null)
                ProcedureEnds(this);
        }

        private void OnNewVersionAdd(object sender, IProcedure proc)
        {
            if (NewVersionAdd != null)
                NewVersionAdd(sender, proc);
        }

        private void OnVersionChange(object sender, VersionChangeEventArgs e)
        {
            if (VersionChange != null)
                VersionChange(sender, e);
        }

        private void OnProcedureUpdate(object sender, IProcedure proc)
        {
            if (ProcedureUpdate != null)
                ProcedureUpdate(sender, proc);
        }

        private void OnNewQueryFounded(object sender, ReturnFullRowEventHandler e)
        {
            if (!_queryList.Exists(q => q.QueryString == e.FullRow[e.Table.ColumnNameForData].ToString()))
            {
                AddNewQuery(sender, e);
            }
            else
            {
                foreach (Procedure tmpproc in this._procedureList)
                {
                    if (tmpproc.Type == Procedure.EnumProcType.New)
                    {
                        if (tmpproc.ListOfVariable.Count == 0)
                        {
                            AddNewQuery(sender, e);
                        }
                        break;
                    }
                }
            }
        }

        public void Marge(ProcedureInfo procedure)
        {
            _isopen = (_isopen || procedure._isopen) ? true : false;
            //if (_isopen || procedure._isopen) _isopen = true; else _isopen = false;
            _looking = (_looking || procedure._looking) ? true : false;
            //if (_looking || procedure._looking) _looking = true; else _looking = false;
            _visible = (_visible || procedure._visible) ? true : false;
            //if (_visible || procedure._visible) _visible = true; else _visible = false;
        }

        private void AddNewVersion(ProcedureVersion procedureVersion)
        {
            OnNewVersionAdd(this, procedureVersion.Parent);
            _knownVersionList.Add(procedureVersion);

            if (!_procedureList.Exists(p => p.Hash == procedureVersion.Hash))
                _procedureList.Add((Procedure)procedureVersion.Parent);
        }

        private void ChangeVersion(object sender, VersionChangeEventArgs e)
        {
            OnVersionChange(sender, e);
            if (_knownVersionList.Exists(v => v.Version == e.Old.Version))
            {
                var tmpVer = _knownVersionList.Find(v => v.Version == e.Old.Version);
                tmpVer.Version = e.New.Version;
                tmpVer.Date = e.New.Date;
                tmpVer.Comment = e.New.Comment;
                tmpVer.Hash = e.New.Hash;
                tmpVer.Project = e.New.Project;
                tmpVer.User = e.New.User;
            }


            //if (!_procedureList.Exists(p => p.Hash == procedureVersion.Hash))
            //    _procedureList.Add((Procedure)procedureVersion.Parent);
        }

        private void AddNewQuery(object sender, ReturnFullRowEventHandler e)
        {
            Query tmpq = new Query(
                this, e.FullRow[e.Table.ColumnNameForData].ToString(),
                DBNull.Value == e.FullRow[e.Table.ColumnNameForDuration] ? (int?)null : Convert.ToInt32(e.FullRow[e.Table.ColumnNameForDuration]),//Convert.ToInt32(e.FullRow["Duration"]),
                DBNull.Value == e.FullRow[e.Table.ColumnNameForReads] ? (int?)null : Convert.ToInt32(e.FullRow[e.Table.ColumnNameForReads]),//Convert.ToInt32(e.FullRow["Reads"]),
                DBNull.Value == e.FullRow["Writes"] ? (int?)null : Convert.ToInt32(e.FullRow["Writes"]),//Convert.ToInt32(e.FullRow["Writes"]),
                DBNull.Value == e.FullRow["CPU"] ? (int?)null : Convert.ToInt32(e.FullRow["CPU"]),
                DBNull.Value == e.FullRow[e.Table.ColumnNameForStartTime] ? (DateTime?)null : DateTime.Parse(e.FullRow[e.Table.ColumnNameForStartTime].ToString())
                );
            tmpq.FoundPath = e.FullRow["Source"].ToString();
            this._queryList.Add(tmpq);
            this._dateOfLastDataFound = tmpq.StartDate.Value;
            OnAddNewQuery(sender, new NewQueryFoundEventArgs(this, tmpq));
        }

        private void ProcedureVersionUpdate(IProcedure procedure)
        {
            OnProcedureUpdate(this, procedure);
            _procedureList[_procedureList.IndexOf(_procedureList.Find(p => p.Version.Version == procedure.Version.Version))] = (Procedure)procedure;
            //_procedureList.Find(p => p.Version.Version == procedure.Version.Version) = (Procedure)procedure;
        }

        public void SetProcDetailsFromBase(ProcedureFromDatabase procedure)
        {
            if (!_procedureList.Exists(p => p.Hash == procedure.Hash))
            {
                //System.Threading.Thread tst =new System.Threading.Thread(new System.Threading.ThreadStart(delegate
                System.Threading.ThreadPool.QueueUserWorkItem(delegate
                {
                    try
                    {
                        if (!procedure.ReadDatabase()) throw new Exception(string.Format("Cannot get data from {0}.{1}", procedure.Server, procedure.DataBase));
                        lock (_procedureList)
                        {
                            SetProcDetails(procedure);
                            procedure.Location = string.Format("{0}.{1}.{2}.{3}", procedure.Server, procedure.DataBase, procedure.Owner, procedure.Name);
                            procedure.Source = string.Format("DataBase {0}", procedure.Location);
                            procedure.VersionChange += new VersionChangeEventHandler(procedure_VersionChange);
                        }
                        if (NewStatus != null) NewStatus(string.Format("Set procedure {0} from DataBase: {1}.", this.Name, procedure.Parent == null ? "" : procedure.Parent.ToString()));
                    }
                    catch (Exception ex)
                    {
                        OnError(this, ex);
                    }
                });
            }
            else
            {
                var tmpProc = (ProcedureFromDatabase)_procedureList.Find(p => p.Hash == procedure.Hash);
                tmpProc.Location = procedure.Location;
                tmpProc.Server = procedure.Server;
                tmpProc.DataBase = procedure.DataBase;
                tmpProc.Owner = procedure.Owner;
                //tmpProc.Location = string.Format("{0}.{1}.{2}.{3}", procedure.Server, procedure.DataBase, procedure.Owner, procedure.Name);
            }
        }

        public void SetProcDetailsFromFile(ProcedureFromFile procedure)
        {
            if (!_procedureList.Exists(p => p.Hash == procedure.Hash))
            {
                //System.Threading.Thread tst =new System.Threading.Thread(new System.Threading.ThreadStart(delegate
                System.Threading.ThreadPool.QueueUserWorkItem(delegate
                {
                    try
                    {
                        if (!procedure.ReadFile()) throw new Exception("Cannot read file " + procedure.Location);
                        lock (_procedureList)
                        {
                            SetProcDetails(procedure);
                            procedure.Source = "File " + procedure.Location;
                            procedure.VersionChange += new VersionChangeEventHandler(procedure_VersionChange);

                            if (NewStatus != null) NewStatus(string.Format("Set procedure {0} from File: {1}.", this.Name, procedure.Location));
                        }
                    }
                    catch (Exception ex)
                    {
                        OnError(this, ex);
                    }
                });
            }
            else
                _procedureList.Find(p => p.Hash == procedure.Hash).Location = procedure.Location;
        }

        private void procedure_VersionChange(object sender, VersionChangeEventArgs e)
        {
            if(_knownVersionList.Exists(v=>v.Version == e.Old.Version))
            {
                ChangeVersion(sender, e);
            }
        }

        public void SetProcDetails(IProcedure procedure)
        {
            if (!_procedureList.Exists(p => p.Hash == procedure.Hash))
            {
                if (!_knownVersionList.Exists(v => v.Version == procedure.Version.Version)
                    || (procedure.Version.Version == ProcedureVersion.Unknown && !_knownVersionList.Exists(v => v.Date == procedure.CreationTime)))
                {
                    AddNewVersion(procedure.Version);
                }
                else
                {
                    ProcedureVersionUpdate(procedure);
                }
                /*
#if DEBUG
                System.Windows.Forms.Form procform = new System.Windows.Forms.Form();
                System.Windows.Forms.UserControl uc = procedure.Show();
                procform.Controls.Add(uc);
                procform.AutoSize = true;
                //procform.ShowInTaskbar = false;
                procform.ShowIcon = false;
                procform.ShowDialog();//.Show();
#endif
                */
                //if (NewVersionAdd != null)
                //    NewVersionAdd(this, procedure);
                _knownVersionList.Sort(delegate(ProcedureVersion pv1, ProcedureVersion pv2)
                {
                    lock (this)
                    {
                        if (pv1.Version == ProcedureVersion.Unknown || pv2.Version == ProcedureVersion.Unknown)
                            return pv1.Date.CompareTo(pv2.Date);
                        //return pv1.Version.CompareTo(pv2.Version);
                        return pv1.CompareTo(pv2);
                    }
                });
                if (_knownVersionList.Count >= 1)
                    SetProcType(_knownVersionList[0].Parent, Procedure.EnumProcType.New);//last
                if (_knownVersionList.Count >= 2)
                    SetProcType(_knownVersionList[1].Parent, Procedure.EnumProcType.Old);//before last
                if (_knownVersionList.Count >= 3)
                    for (int i = 3; i < _knownVersionList.Count; i++)
                    {
                        SetProcType(_knownVersionList[i].Parent, Procedure.EnumProcType.None);
                    }
            }
            //});
            //tst.Start();
            //}
        }

        public void SetProcType(IProcedure proc, Procedure.EnumProcType type)
        {
            proc.Type = type;
        }

        internal void OpenResultFile()
        {
            Settings.Instance.ProjectSettings.OnOpenProcedure(this, new OpenFormEventArgs(new Forms.frmResult(this)));
        }

        internal void OpenResultText()
        {
            //Settings.Instance.ProjectSettings.OnOpenProcedure(this, new OpenFormEventArgs(new Forms.frmResult(this)));
            Settings.Instance.ProjectSettings.OnOpenProcedure(this, new OpenFormEventArgs(_result.ResultString.ToString()));
        }

        internal void OpenResultList()
        {
            //Settings.Instance.ProjectSettings.OnOpenProcedure(this, new OpenFormEventArgs(new Forms.frmResult(this)));
            System.Windows.Forms.ListBox lb = new System.Windows.Forms.ListBox();
            lb.DataSource = _queryList;
            Settings.Instance.ProjectSettings.OnOpenProcedure(this, new OpenFormEventArgs(lb));
        }

        internal void OpenResultGrid()
        {
            //Settings.Instance.ProjectSettings.OnOpenProcedure(this, new OpenFormEventArgs(new Forms.frmResult(this)));
            //Settings.Instance.ProjectSettings.OnOpenProcedure(this, new OpenFormEventArgs(_result.ResultString.ToString()));
        }

        internal void OpenFileLocation()
        {
            string directory;

            if (System.IO.File.Exists(ResultFile))
            {
                System.IO.FileInfo fi = new System.IO.FileInfo(ResultFile);
                directory = fi.DirectoryName;
            }
            else
            {
                directory = Library.Objects.ProjectSettings.Instance.ProjectResultsLocation;
            }
            if (System.IO.Directory.Exists(directory))
            {
                string myPath = Library.Objects.ProjectSettings.Instance.ProjectResultsLocation;
                string myFile = myPath + "\\" + Name + ".txt";
                System.Diagnostics.Process prc = new System.Diagnostics.Process();
                prc.StartInfo.FileName = myPath;
                prc.Start();
            }
            else
            {
                //_project.Procedures[dataGridView_LookingProcedures.SelectedRows[0].Cells[Procedures.Name].Value].
            }
        }
        #endregion

        #region IProcedureInfo Members


        public IProcedureInfo GetProcedure()
        {
            return this;
        }

        #endregion

        public override string ToString()
        {
            return _procedureName;
        }

        private void OnError(object sender, Exception ex)
        {
            if (ErrorEvent != null)
                ErrorEvent(sender, ex);
        }
        private void OnNewStatus(string str)
        {
            if (NewStatus != null)
                NewStatus(str);
        }

        private void OnStatusChange(object sender, ProcedureInfo.Status e)
        {
            if (StatusChange != null)
                StatusChange(sender, e);
        }

        private void OnAddNewQuery(object sender, NewQueryFoundEventArgs e)
        {
            NewQuedyAdd(sender, e);
        }

        #region Serialization
        public System.Xml.Schema.XmlSchema GetSchema()
        {
            throw new NotImplementedException();
        }

        public void ReadXml(XmlReader reader)
        {
            reader.MoveToContent();

            this.Name = reader.GetAttribute("Name");
            Boolean.TryParse(reader.GetAttribute("Loocking"), out this._looking);
            Int32.TryParse(reader.GetAttribute("Found"), out this._found);
            DateTime.TryParse(reader.GetAttribute("StartTime"), out this._starttime);
            DateTime.TryParse(reader.GetAttribute("EndTime"), out this._endtime);
            DateTime.TryParse(reader.GetAttribute("DateOfLastDataFound"), out this._dateOfLastDataFound);
            this.ResultFile = reader.GetAttribute("ResultFile");

            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(reader);
            foreach (XmlNode rootnode in xmldoc.ChildNodes)
                foreach (XmlNode node in rootnode.ChildNodes)
                    foreach (XmlNode tmpNode in node.ChildNodes)
                    {
                        String className = tmpNode.Name.Trim(); //read the class name 
                        Type objectType = (from asm in AppDomain.CurrentDomain.GetAssemblies()
                                           from type in asm.GetTypes()
                                           where type.IsClass && type.Name == className
                                           select type).SingleOrDefault();//.Single();
                        XmlReader r = new XmlNodeReader(tmpNode);

                        System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(objectType);
                        var obj = Convert.ChangeType(serializer.Deserialize(r), objectType);
                        PinByOjectType(objectType, obj);
                    }
        }

        private void PinByOjectType(Type objectType, object obj)
        {
            switch (objectType.FullName)
            {
                case "Nizm0.QOT.Library.Objects.ProcedureFromDatabase":
                case "Nizm0.QOT.Library.Objects.ProcedureFromFile":
                    {
                        var tmpobj = (Procedure)obj;
                        tmpobj.Parent = this;
                        tmpobj.VersionChange += new VersionChangeEventHandler(procedure_VersionChange);
                        if (tmpobj.Version != null)
                        {
                            AddNewVersion(tmpobj.Version);
                            //_knownVersionList.Add(tmpobj.Version);
                            //_procedureList.Add(tmpobj);
                        }
                        break;
                    }
                case "Nizm0.QOT.Library.Objects.SearchedObject":
                    {
                        _searchedObjectsList.Add((Library.Objects.SearchedObject)obj);
                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteAttributeString("Name", this.Name);
            writer.WriteAttributeString("Loocking", this._looking.ToString());
            writer.WriteAttributeString("Found", this._found.ToString());
            writer.WriteAttributeString("StartTime", this._starttime.ToUniversalTime().ToString());
            writer.WriteAttributeString("EndTime", this._endtime.ToUniversalTime().ToString());
            writer.WriteAttributeString("DateOfLastDataFound", this._dateOfLastDataFound.ToUniversalTime().ToString());
            writer.WriteAttributeString("ResultFile", this._resultFile);
            writer.WriteStartElement("Procedures");
            foreach (IProcedure proc in _procedureList)
            {
                var nsSerializer = new XmlSerializerNamespaces();
                nsSerializer.Add("", "");
                System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(proc.GetType(), "");
                xmlSerializer.Serialize(writer, proc, nsSerializer);
            }
            writer.WriteEndElement();
            writer.WriteStartElement("SerchedObjectsList");
            foreach (SearchedObject sobj in SearchedObjectsList)
            {
                var nsSerializer = new XmlSerializerNamespaces();
                nsSerializer.Add("", "");
                System.Xml.Serialization.XmlSerializer xmlSerializer = new System.Xml.Serialization.XmlSerializer(sobj.GetType(), "");
                xmlSerializer.Serialize(writer, sobj, nsSerializer);
            }
            writer.WriteEndElement();
            //writer.WriteStartElement("ProcedureInfo");
            //writer.WriteAttributeString("Name", this.Name);
            //writer.WriteEndElement();
            writer.Flush();
        }

        public static T Deserialize<T>(string xmlobject)
                    where T : class
        {
            byte[] byteArray = Encoding.ASCII.GetBytes(xmlobject);
            MemoryStream stream = new MemoryStream(byteArray);
            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(T));
            T ip = (T)x.Deserialize(stream);
            return ip;
        }

        public virtual string Serialize()
        {
            using (Stream str = new MemoryStream())
            {
                //System.Runtime.Serialization.Formatters.Binary.BinaryFormatter t = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(
                System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(ProcedureInfo));
                x.Serialize(str, this);
                XmlDocument xDocument = new XmlDocument();
                str.Position = 0;
                xDocument.Load(str);
                return xDocument.OuterXml;
                //using (StreamReader stmr = new StreamReader(str))
                //{
                //    return stmr.ReadToEnd();
                //}
            }
        }
        #endregion

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("Name", this.Name);
            //info.AddValue("Result", this._procedureList);

        }
    }
}
